/* ========================================================================
 * Copyright (c) 2005-2013 The OPC Foundation, Inc. All rights reserved.
 *
 * OPC Reciprocal Community License ("RCL") Version 1.00
 * 
 * Unless explicitly acquired and licensed from Licensor under another 
 * license, the contents of this file are subject to the Reciprocal 
 * Community License ("RCL") Version 1.00, or subsequent versions 
 * as allowed by the RCL, and You may not copy or use this file in either 
 * source code or executable form, except in compliance with the terms and 
 * conditions of the RCL.
 * 
 * All software distributed under the RCL is provided strictly on an 
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
 * AND LICENSOR HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 
 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
 * PURPOSE, QUIET ENJOYMENT, OR NON-INFRINGEMENT. See the RCL for specific 
 * language governing rights and limitations under the RCL.
 *
 * The complete license agreement can be found here:
 * http://opcfoundation.org/License/RCL/1.00/
 * ======================================================================*/

using System;
using System.Collections.Generic;
using System.Text;

namespace Opc.Ua
{
    /// <summary>
    /// This is an interface to a channel which supports 
    /// </summary>
    public interface ITransportChannel : IDisposable
    {
        /// <summary>
        /// A masking indicating which features are implemented.
        /// </summary>
        TransportChannelFeatures SupportedFeatures { get; }

        /// <summary>
        /// Gets the description for the endpoint used by the channel.
        /// </summary>
        EndpointDescription EndpointDescription { get; }

        /// <summary>
        /// Gets the configuration for the channel.
        /// </summary>
        EndpointConfiguration EndpointConfiguration { get; }

        /// <summary>
        /// Gets the context used when serializing messages exchanged via the channel.
        /// </summary>
        ServiceMessageContext MessageContext { get; }

        /// <summary>
        /// Gets or sets the default timeout for requests send via the channel.
        /// </summary>
        int OperationTimeout { get; set; }

        /// <summary>
        /// Initializes a secure channel with the endpoint identified by the URL.
        /// </summary>
        /// <param name="url">The URL for the endpoint.</param>
        /// <param name="settings">The settings to use when creating the channel.</param>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        void Initialize(
            Uri url,
            TransportChannelSettings settings);

        /// <summary>
        /// Opens a secure channel with the endpoint identified by the URL.
        /// </summary>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        void Open();

        /// <summary>
        /// Begins an asynchronous operation to open a secure channel with the endpoint identified by the URL.
        /// </summary>
        /// <param name="callback">The callback to call when the operation completes.</param>
        /// <param name="callbackData">The callback data to return with the callback.</param>
        /// <returns>The result which must be passed to the EndOpen method.</returns>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        /// <seealso cref="Open"/>
        IAsyncResult BeginOpen(
            AsyncCallback callback, 
            object callbackData);

        /// <summary>
        /// Completes an asynchronous operation to open a secure channel.
        /// </summary>
        /// <param name="result">The result returned from the BeginOpen call.</param>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        /// <seealso cref="Open" />
        void EndOpen(IAsyncResult result);

        /// <summary>
        /// Closes any existing secure channel and opens a new one.
        /// </summary>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        /// <remarks>
        /// Calling this method will cause outstanding requests over the current secure channel to fail.
        /// </remarks>
        void Reconnect();

        /// <summary>
        /// Begins an asynchronous operation to close the existing secure channel and open a new one.
        /// </summary>
        /// <param name="callback">The callback to call when the operation completes.</param>
        /// <param name="callbackData">The callback data to return with the callback.</param>
        /// <returns>The result which must be passed to the EndReconnect method.</returns>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        /// <seealso cref="Reconnect" />
        IAsyncResult BeginReconnect(AsyncCallback callback, object callbackData);

        /// <summary>
        /// Completes an asynchronous operation to close the existing secure channel and open a new one.
        /// </summary>
        /// <param name="result">The result returned from the BeginReconnect call.</param>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        /// <seealso cref="Reconnect" />
        void EndReconnect(IAsyncResult result);

        /// <summary>
        /// Closes the secure channel.
        /// </summary>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        void Close();

        /// <summary>
        /// Begins an asynchronous operation to close the secure channel.
        /// </summary>
        /// <param name="callback">The callback to call when the operation completes.</param>
        /// <param name="callbackData">The callback data to return with the callback.</param>
        /// <returns>The result which must be passed to the EndClose method.</returns>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        /// <seealso cref="Close" />
        IAsyncResult BeginClose(AsyncCallback callback, object callbackData);

        /// <summary>
        /// Completes an asynchronous operation to close the secure channel.
        /// </summary>
        /// <param name="result">The result returned from the BeginClose call.</param>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        /// <seealso cref="Close" />
        void EndClose(IAsyncResult result);

        /// <summary>
        /// Sends a request over the secure channel.
        /// </summary>
        /// <param name="request">The request to send.</param>
        /// <returns>The response returned by the server.</returns>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        IServiceResponse SendRequest(IServiceRequest request);

        /// <summary>
        /// Begins an asynchronous operation to send a request over the secure channel.
        /// </summary>
        /// <param name="request">The request to send.</param>
        /// <param name="callback">The callback to call when the operation completes.</param>
        /// <param name="callbackData">The callback data to return with the callback.</param>
        /// <returns>The result which must be passed to the EndSendRequest method.</returns>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        /// <seealso cref="SendRequest" />
        IAsyncResult BeginSendRequest(IServiceRequest request, AsyncCallback callback, object callbackData);

        /// <summary>
        /// Completes an asynchronous operation to send a request over the secure channel.
        /// </summary>
        /// <param name="result">The result returned from the BeginSendRequest call.</param>
        /// <exception cref="ServiceResultException">Thrown if any communication error occurs.</exception>
        /// <seealso cref="SendRequest" />
        IServiceResponse EndSendRequest(IAsyncResult result);
    }

    /// <summary>
    /// The masks for the optional features which may not be supported by every transport channel.
    /// </summary>
    [Flags]
    public enum TransportChannelFeatures
    {
        /// <summary>
        /// The channel does not support any optional features.
        /// </summary>
        None = 0x0000,

        /// <summary>
        /// The channel supports Open.
        /// </summary>
        Open = 0x0001,

        /// <summary>
        /// The channel supports asynchronous Open.
        /// </summary>
        BeginOpen = 0x0002,

        /// <summary>
        /// The channel supports Reconnect.
        /// </summary>
        Reconnect = 0x0004,
        
        /// <summary>
        /// The channel supports asynchronous Reconnect.
        /// </summary>
        BeginReconnect = 0x0008,

        /// <summary>
        /// The channel supports asynchronous Close.
        /// </summary>
        BeginClose = 0x0010,

        /// <summary>
        /// The channel supports asynchronous SendRequest.
        /// </summary>
        BeginSendRequest = 0x0020
    }
}
